using System;
using System.Collections;
using System.Reflection;
using System.Data;
using System.Globalization;

using Microsoft.SharePoint;
using Microsoft.SharePoint.Portal;
using Microsoft.SharePoint.Utilities;
using Microsoft.SharePoint.Portal.Admin;
using Microsoft.SharePoint.Portal.SiteData;
using Microsoft.SharePoint.Portal.Topology;
using Microsoft.SharePoint.Portal.Security;
using Microsoft.SharePoint.Portal.UserProfiles;
using System.IO;
using Microsoft.Win32;
using System.Security.Principal;
using System.Runtime.InteropServices;
using System.Security;
using System.Text;
using System.ComponentModel;
using SharePoint.ImportExport.Core;


using System.Xml;
using System.Xml.Serialization;

namespace SharePoint2003.Import
{
	

		

	/// <summary>
	/// This is the wrapper class for handling Portal Server functions.
	/// </summary>
	public class PortalWrapper
	{


		private SPWeb Web;
		private bool WebOpen=false;
		private PortalContext ThisPortalContext=null;

		private Guid AreaID=Guid.Empty;
		private static readonly PortalRight PortalAreaReader = PortalRight.ViewArea |
			PortalRight.ViewPages;

		private static readonly PortalRight PortalAreaContributor = PortalAreaReader |
			PortalRight.AddListItems |
			PortalRight.EditListItems |
			PortalRight.DeleteListItems |
			PortalRight.ManagePersonalViews |
			PortalRight.AddDelPrivateWebParts |
			PortalRight.UpdatePersonalWebParts |
			PortalRight.BrowseDirectories ;

		//private static readonly PortalRight PortalAreaAdministrator = PortalRight.AllCategoryRights ;

		private static readonly PortalRight PortalSiteReader = PortalRight.ViewArea |
			PortalRight.ViewPages |
			PortalRight.UseSearch ;

		private static readonly PortalRight PortalSiteContributor = PortalSiteReader |
			PortalRight.AddListItems |
			PortalRight.EditListItems |
			PortalRight.DeleteListItems |
			PortalRight.ManagePersonalViews |
			PortalRight.AddDelPrivateWebParts |
			PortalRight.UpdatePersonalWebParts |
			PortalRight.BrowseDirectories |
			PortalRight.CreatePersonalSite |
			PortalRight.CreateSSCSite |
			PortalRight.UseSubscriptions ;

		//private static PortalRight PortalSiteAdministrator = PortalRight.AllSiteRights | PortalRight.AllCategoryRights;
		
	
		#region Security
		/// <summary>
		/// This flag indicates whether the registry SID is updated or not
		/// </summary>
		private bool setSID=false;

		/// <summary>
		/// 
		/// </summary>
		public enum SecurityError
		{

			/// <summary>
			/// Success=0
			/// </summary>
			Success		 = 0,
			/// <summary>
			/// Unknown=1
			/// </summary>
			Unknown =1,
			/// <summary>
			/// AlreadySet =2
			/// </summary>
			AlreadySet =2,
			/// <summary>
			/// NotLocalAdmin = 3
			/// </summary>
			NotLocalAdmin  =3
	};
		/// <summary>
		/// Function that removes the security key
		/// </summary>
		/// <returns></returns>
		public SecurityError ClearSecurity()
		{

			SecurityError retvalue=SecurityError.Unknown;
			if(!setSID)
				return retvalue;

			RegistryKey regkey_LocalMachine = Registry.LocalMachine;
			RegistryKey regkey_SPS=null ;
			const string sSubKey = "Software\\Microsoft\\SharePoint Portal Server";
			const string sSIDKey = "FullControlSID";

			try
			{

				regkey_SPS = regkey_LocalMachine.OpenSubKey(sSubKey,true);
				if(null!=regkey_SPS)
				{
					regkey_SPS.DeleteValue(sSIDKey,false);
					//Perform a IISReset
					ServiceManager sm = new ServiceManager();
					sm.IISReset();
					Logger.Log(ErrorLevel.Information,"Registry Key FullControlSID removed and IIS restarted");
				}
				else
				{
					Logger.Log(ErrorLevel.Error,"Could not remove the value FullControlSID from the registry key "+sSubKey);
				}
			}
			catch(SecurityException SecEx)
			{
				Logger.Log(ErrorLevel.Error, "Error when clearing the security registry key: "+sSubKey+"\\"+sSIDKey+". Error: "+SecEx.Message+". Please remove it manually");
			}
			finally
			{
				if(null != regkey_SPS) regkey_SPS.Close();
				if(null != regkey_LocalMachine) regkey_LocalMachine.Close();
			}


			return retvalue;
		}

		/// <summary>
		/// 
		/// </summary>
		/// <returns>a boolean to indicate whether security was set</returns>
		public SecurityError SetSecurity()
		{
			SecurityError retvalue=SecurityError.Unknown;


			const string subKey = "Software\\Microsoft\\SharePoint Portal Server";
			const string SIDKey = "FullControlSID";
			RegistryKey regkey_LocalMachine = null;
			RegistryKey regkey_SPS = null;
			byte[] sid = GetSIDOfCurrentUser();

			if(!NativeMethods.IsCurrentUserMemberOfLocalAdmin())
				return SecurityError.NotLocalAdmin;
				
			try
			{
				regkey_LocalMachine = Registry.LocalMachine;

				regkey_SPS = regkey_LocalMachine.OpenSubKey(subKey,true);
				if(null==regkey_SPS)
				{
					return SecurityError.Unknown;
				}
				object sidinRegistry;
				
				sidinRegistry=regkey_SPS.GetValue(SIDKey);
				if(null==sidinRegistry)
					setSID=true;
				else
				{
					byte[]bsidinRegistry=(byte[])sidinRegistry;
					if(bsidinRegistry.Length!=sid.Length)
						{
							setSID=true;
						}
					else
					{
						for(int i=0;i<sid.Length;i++)
						{
							if(sid[i]!=bsidinRegistry[i])
							{
								setSID=true;

								break;
							}
						}
					}

				}
				if(setSID)
				{
					regkey_SPS.SetValue(SIDKey,sid);
					//Perform a IISReset
					ServiceManager sm = new ServiceManager();
					sm.IISReset();
					Logger.Log(ErrorLevel.Information,"FullControlSID set and IIS restarted");
					retvalue=SecurityError.Success;
				}
				else
				{
					retvalue=SecurityError.AlreadySet;
				}


			}
			catch(SecurityException sExc)
			{
				Logger.Log(ErrorLevel.Error,"SecurityException occurred when setting the registry key. Error: "+sExc.Message);
			}
			catch(NullReferenceException nExc)
			{
				Logger.Log(ErrorLevel.Error,"NullReferenceException occurred when setting the registry key. Error: "+nExc.Message);
			}
			finally
			{
				if(null != regkey_SPS) regkey_SPS.Close();
				if(null != regkey_LocalMachine) regkey_LocalMachine.Close();
			}
			return retvalue;

		}
		/// <summary>
		/// Get the SID of the current user as a byte array
		/// </summary>
		private static byte[] GetSIDOfCurrentUser()
		{
			string name = "";
			try
			{
				WindowsPrincipal wp = new WindowsPrincipal(WindowsIdentity.GetCurrent());
				name=wp.Identity.Name;
			}
			catch(Exception ex)
			{
				Logger.Log(ErrorLevel.Error,"Exception in (GetSIDOfCurrentUser): "+ex.Message);

				throw ex;
			}
			
			
			//string[] identity = name.Split(new char[]{'\\'},2);
			//Debug.Assert(identity.Length == 2, "Login Name not of the form domain\\username"); 


			//name can be of form domain\username OR UPN
			byte[] sid = NativeMethods.LookupAccountName(name);
 
			return sid;
		}

		#endregion
		/// <summary>
		/// This is the constructor for the portal wrapper class. It instantiates a log file called "portalwrapper.log"
		/// </summary>
		public PortalWrapper()
		{
			
		}
	
		/// <summary>
		/// This member closes the portal and its underlying SPWeb
		/// </summary>
		public void ClosePortal()
		{
			ThisPortalContext = null;
			if(null!=Web)
				Web.Close();
			ClearSecurity();
		}
		/// <summary>
		/// This method open the portal specified by the siteUrl parameter
		/// </summary>
		/// <param name="portalUri"></param>
		/// <returns></returns>
		public bool OpenPortal(Uri portalUri)
		{
			Logger.Log(ErrorLevel.Information, "Opening the portal specified by "+portalUri.ToString());
			bool bOK=false;
			
			TopologyManager topology = new TopologyManager();
			PortalSite portalSite = topology.PortalSites[portalUri];
			if(null!=portalSite)
			{
				ThisPortalContext = PortalApplication.GetContext(portalSite);
				bOK=true;
			}
			return bOK;

		}
		/// <summary>
		/// This method returns the ID of the Portal area specified by the rootArea parameter
		/// This parameter can point to a hierarchy root, e.g. http://server/Topics or further down eg http://server/Topics/SubArea/SubSubArea
		/// </summary>
		/// <param name="rootArea"></param>
		/// <returns></returns>
		public string GetSystemAreaGuid(string rootArea)
		{
			rootArea=rootArea.Replace("%20"," ");
			string [] areas=rootArea.Split("/".ToCharArray());
			string returnGuid=String.Empty;
			try
			{
				Area area=null;
				try
				{
					SystemArea sysArea = (SystemArea)Enum.Parse(typeof(SystemArea), areas[0],true);
					Guid guid = AreaManager.GetSystemAreaGuid(ThisPortalContext, sysArea );
					area=AreaManager.GetArea(ThisPortalContext,guid);
				
				}
				catch(ArgumentException argEx)
				{
					//Check from home -- as rootArea might be renamed or we might be importing elsewhere
					SystemArea eSysArea = SystemArea.Home;
		
					Guid eGuid = AreaManager.GetSystemAreaGuid(ThisPortalContext, eSysArea);
					area=AreaManager.GetArea(ThisPortalContext,eGuid);
					if(areas[0].Length>0)
						area=area.Areas[areas[0]];
				}

				
				for(int i=1;i<areas.Length;i++)
				{
					area=area.Areas[areas[i]];
				}
				returnGuid=area.ID.ToString();
			}

			catch(NullReferenceException NullEx)
			{
				Logger.Log(ErrorLevel.Error,"Could not resolve the area "+rootArea+". Error: "+NullEx .Message);
			}
			catch(ArgumentException ArgEx)
			{
				Logger.Log(ErrorLevel.Error,"Could not resolve the area "+rootArea+". Error: "+ArgEx.Message);
			}
			return returnGuid;

		}

		/// <summary>
		/// This method adds the user defined in the XML node to the portal
		/// </summary>
		/// <param name="user"></param>
		/// <param name="roleName"></param>
		/// <param name="g"></param>
		/// <returns></returns>
		private bool AddUser(SharePoint.ImportExport.Core.User user, string roleName, Guid g)
		{
			bool bRetVal=false;
			try
			{
				string account=user.Account;
					
				if(0==String.Compare(user.Account,Web.CurrentUser.LoginName,true,CultureInfo.InvariantCulture))
					return false;
				if(0==String.Compare(user.Account,"everyone",true,CultureInfo.InvariantCulture))
					account = @"nt authority\authenticated users";
				string email = user.Email;
				if(null==email)
					email="";
				string displayname =user.Name;;
				if(null==displayname )
					displayname="";
				if(email.Length==0||displayname.Length==0)

					{

						try
						{
							SPUtility.GetNTFullNameandEmailfromLogin(Web,account,out displayname,out email);
						}
						catch(SPException spEx)
						{
							Logger.Log(ErrorLevel.Information,spEx.Message);
							string[] sResults = GetAccountEmailDisplayName(account,new Uri(Web.Url));
							displayname = sResults[0];
							email = sResults[1];

						}
					}
				bool bAddedUser=false;
						
				if(account.Length>0)
					{
						/*//Try to add the user to the underlying Web
						SPRoleCollection roles=Web.Roles;
						foreach(SPRole r in roles)
						{
							if(0==String.Compare(r.Type.ToString(),roleName,true,CultureInfo.InvariantCulture))
							{
								r.AddUser(account,email,displayname,"");
								bAddedUser=true;
								break;
							}
						}
						*/

						if(!bAddedUser)
						{
							PortalRight oPermissions = PortalRight.ViewPages | PortalRight.ViewArea | PortalRight.BrowseDirectories;
							switch(roleName)
							{
								case "Contributor":
									oPermissions = PortalRight.ViewPages | PortalRight.ViewArea 
										| PortalRight.AddListItems | PortalRight.EditListItems | PortalRight.DeleteListItems;
									break;
								case "Administrator":
									oPermissions = PortalRight.AllCategoryRights;
									
									break;
							}
							Logger.Log(ErrorLevel.Information,"Attempting to add: " + account + " (" + email + " : " + displayname + ")");
							PermissionCollection oPc = Microsoft.SharePoint.Portal.Security.SecurityManager.ManageAreaSecurity(ThisPortalContext, g);
							oPc.AddUser(account,email,displayname,"",oPermissions);
							
							Logger.Log(ErrorLevel.Information,"Added user: " + account + " (" + email + " : " + displayname + ")");
							

						}

						


						bRetVal=true;
					}
			}
			catch(SPException spExc)
			{
				Logger.Log(ErrorLevel.Error,"Could not add the user "+user.Account+". Error: "+spExc.Message);
				
				return false;
			}
			return bRetVal;


		}
		/// <summary>
		/// Method for adding an area. This method does not try to add any users to the area
		/// </summary>
		/// <param name="parentAreaGuid"></param>
		/// <param name="name"></param>
		/// <param name="title"></param>
		/// <returns></returns>
		public string CreateSimple(Guid parentAreaGuid, string name, string title)
		{
			Area parentArea = AreaManager.GetArea(ThisPortalContext, parentAreaGuid);
			Area area = parentArea.Areas.AddArea(name);
			area.Title = title;
			area.Update();
			return area.ID.ToString();
		}
		/// <summary>
		/// Method for adding an area. 
		/// </summary>
		/// <param name="parentAreaGuid">This is the ID of the area under which the area will be created</param>
		/// <param name="portalUri"></param>
		/// <param name="container">This is the class representing the node from the struct.xml file</param>
		/// <param name="enableSecurity"></param>
		/// <param name="allowImportToAnExistingArea"></param>
		/// <returns></returns>
		public string Create(Guid parentAreaGuid,Uri portalUri, SharePoint.ImportExport.Core.Container container,bool enableSecurity, bool allowImportToAnExistingArea )
		{
			Guid g=Guid.Empty;
			try
			{
				string defaultvalue="";
	
				if(WebOpen)
					defaultvalue=Web.CurrentUser.Email;

				string sEmail = container.Contact;
				if(WebOpen)
					defaultvalue=Web.CurrentUser.LoginName;

				string account = container.Owner;
				
				string sDisplayname="";
			
				Area ParentArea = AreaManager.GetArea(ThisPortalContext, parentAreaGuid);
				Area spArea = null;
				if(allowImportToAnExistingArea)
				{

					try
					{
						spArea = ParentArea.Areas[container.Name];
						g=spArea.ID;
						
						SPSite m_site2 = new SPSite(portalUri.ToString()+spArea.WebUrl);
						Web = m_site2.OpenWeb();
						WebOpen=true;
						Logger.Log(ErrorLevel.Progress,"Area "+container.Name+" opened");

						return g.ToString();
					}
					catch(System.NullReferenceException nullEx)
					{
						spArea = null;
					}
					
					catch(Microsoft.SharePoint.Portal.SiteData.AreaNotExistException areaEx)
					{
						spArea = null;
					}
				}
				//instead of trusting that area exist -- create it even if AllowImportToAnExistingSite is on
				//but it could not be found -- this way top-level area can exist, but new childs will be created
				if(spArea == null)
				{
					string template=container.Template;
					if(null==container.Template)
						template="";

					
					if(template.Length>0)
					{
						SPSite sitetemp = null;
						try
						{
							sitetemp =new SPSite(portalUri+ParentArea.WebUrl);
				
							spArea = ParentArea.Areas.AddArea(container.Name,ParentArea.Web.Name,container.Template,sitetemp);
							Logger.Log(ErrorLevel.Progress,"Area "+container.Name+" created");
						}
						catch(SPException Ex)
						{
							Logger.Log(ErrorLevel.Information,Ex.Message);
						}
						finally
						{
							if(null!=sitetemp)
							{
								sitetemp.Close();
								sitetemp.Dispose();
							}
						}
					}
					else
					{
						spArea = ParentArea.Areas.AddArea(container.Name);
						Logger.Log(ErrorLevel.Progress,"Area "+container.Name+" created");
					}
					g=spArea.ID;
				}
			
				string sURL=portalUri.ToString();
				sURL=sURL.Substring(0,sURL.Length-portalUri.AbsolutePath.Length);
				sURL+=spArea.WebUrl;
				SPSite m_site = new SPSite(sURL);
				Web = m_site.OpenWeb();
				WebOpen=true;
				if(container.Owner.Length>0)
				{
					try
					{
						SPUtility.GetNTFullNameandEmailfromLogin(Web,container.Owner,out sDisplayname,out sEmail);
					}
					catch(SPException ex)
					{
						Logger.Log(ErrorLevel.Warning,ex.Message);
					}
					if(null==sDisplayname)
						sDisplayname=container.Owner;
					if(null==sEmail)
						sEmail=container.Contact;

					spArea.Owner=sDisplayname;
					spArea.OwnerEmail=sEmail;
				}
				spArea.Title = container.Name;
				spArea.Description=container.Description;
				
				if(enableSecurity)
				{
					if(!container.InheritPermissions)
						Logger.Log(ErrorLevel.Information,"Area "+container.Name+ " has unique permissions");
					spArea.InheritSecurity=container.InheritPermissions;
					PermissionCollection pc = Microsoft.SharePoint.Portal.Security.SecurityManager.ManageAreaSecurity(ThisPortalContext,spArea.ID );
					if(!container.InheritPermissions)
					{
						//Remove the users
						
						ArrayList usersAndRoles=new ArrayList();
						foreach(Permission perm in pc)
						{
							usersAndRoles.Add(perm);
							Microsoft.SharePoint.Portal.Security.User usr = perm.Member as Microsoft.SharePoint.Portal.Security.User;
							Microsoft.SharePoint.Portal.Security.Role role = perm.Member as Microsoft.SharePoint.Portal.Security.Role;
							if (usr!=null)
								Logger.Log(ErrorLevel.Information,"Removing user: "+usr.Name);
							else
								Logger.Log(ErrorLevel.Information,"Removing role: "+role.Name);
						}
						foreach(object o in usersAndRoles)
						{
							Permission permission=(Permission)o;
							pc.Remove(permission.Member);
						}

					}
					foreach(SharePoint.ImportExport.Core.Role role in container.Security.Roles)
					{
						try
						{
							Microsoft.SharePoint.Portal.Security.PortalRight rights=(PortalRight)Enum.Parse(typeof(PortalRight),role.Permissions,true);
							int Pos=role.Xml.IndexOf("Description=");
							string roleDescription="";
							if(Pos>0)
								roleDescription=role.Xml.Substring(Pos+13);
							Pos=roleDescription.IndexOf("\"");
							if(Pos>0)
								roleDescription=roleDescription.Substring(0,Pos);
							Microsoft.SharePoint.Portal.Security.Role spRole=Microsoft.SharePoint.Portal.Security.SecurityManager.AddRole(ThisPortalContext,role.RoleName,roleDescription,rights);
							//ToDO pc.Add(spRole,rights);
							

						}
						catch(SPException roleEx)
						{
							if(roleEx.ErrorCode!=-2130575293)
							{
								Logger.Log(ErrorLevel.Error,"Could not add the role "+role.RoleName+". Error: "+roleEx.Message);
							}

						}
						catch(Exception roleEx2)
						{
							Logger.Log(ErrorLevel.Error,"Could not add the role "+role.RoleName+". Error: "+roleEx2.Message);
						}
					}
					foreach(SharePoint.ImportExport.Core.User user in container.Security.Users)
					{
						string roleName =user.Role.ToLower(System.Threading.Thread.CurrentThread.CurrentCulture);

						if(roleName=="editor")
							roleName="contributor";
						if(user.Account.ToLower(System.Threading.Thread.CurrentThread.CurrentCulture) != "everyone")
							AddUser(user, roleName, spArea.ID);
					}
	
				}
			
				spArea.Update();
			}
			catch(Microsoft.SharePoint.Portal.SiteData.AreaDuplicateException AreaEx)
			{
				Logger.Log(ErrorLevel.Error,"The area "+container.Name+" already exists. Error: "+AreaEx.Message);
				
			}

			catch(Microsoft.SharePoint.Portal.SiteData.ProvisionAreaFailureException Ex)
			{
				Logger.Log(ErrorLevel.Error,"Error when creating an area. Error: "+Ex.Message);
				
			}
			
			return g.ToString();

	
		}
		/// <summary>
		/// This method returns the URL of the area specified by the parameter areaGuid
		/// </summary>
		/// <param name="areaGuid">This is the ID of the Portal Area</param>
		/// <returns></returns>
		public string GetAreaUrl(Guid areaGuid)
		{
			string areaUrl="";
			try
			{
				Area area = AreaManager.GetArea(ThisPortalContext, areaGuid);
				areaUrl=area.WebUrl;
			}
			catch(Microsoft.SharePoint.Portal.SiteData.AreaNotExistException AreaEx)
			{
				SPSite site=null;
				try
				{
					site= new SPSite(areaGuid);
					areaUrl=	site.ServerRelativeUrl  ;
					
				}
				catch(SPException Ex)
				{
					Logger.Log(ErrorLevel.Error,Ex.Message);
				}
				finally
				{
					if(null!=site)
						site.Close();
				}
			}
			return areaUrl;
			
		}
		/// <summary>
		/// This method deleted the portal area specified by the areaGuid parameter
		/// </summary>
		/// <param name="areaGuid">This is the ID of the Portal Area</param>
		public void DeleteArea(Guid areaGuid)
		{
			Area spArea = AreaManager.GetArea(ThisPortalContext, areaGuid);
			spArea.Delete();
		}

		/// <summary>
		/// This method adds the WSS site specified by the urlSite parameter to the portal search
		/// </summary>
		/// <param name="title">This is the title of the WSS site</param>
		/// <param name="description">This is the description of the WSS site</param>
		/// <param name="siteUri">This is the URL of the WS Site</param>
		/// <param name="portalUri">This is the URL to the Portal</param>
		public void AddSiteToEnableSearch(string title, string description, Uri siteUri, Uri portalUri)
		{
			
			if(null == ThisPortalContext)
				OpenPortal(portalUri);
			if(null != ThisPortalContext)
				AreaManager.SuggestDeepCrawl(ThisPortalContext,title,description,siteUri.LocalPath,"","","$$$default$$$", "$$$default$$$");
		}
		/// <summary>
		/// This method reads the user info from the Portal profile database
		/// </summary>
		/// <param name="domainName">This is the domain account of the user</param>
		/// <param name="portalRootUri">This is the Protal root</param>
		/// <returns></returns>
		public string[] GetAccountEmailDisplayName(string domainName, Uri portalRootUri)
		{
			string[] sResults = new string[2];
			sResults[0] = domainName;
			sResults[1] = "Not Found";
			if(null == ThisPortalContext)
			{
				TopologyManager topology = new TopologyManager();
				PortalSite portalSite = topology.PortalSites[portalRootUri];
				ThisPortalContext = PortalApplication.GetContext(portalSite);
			}


			try
			{
				UserProfileManager oPM = new UserProfileManager(ThisPortalContext);
				UserProfile oProfile = oPM.GetUserProfile(domainName);
				sResults[0] = (string)oProfile["PreferredName"];
				sResults[1] = (string)oProfile["WorkEmail"];
			}
			catch(Microsoft.SharePoint.Portal.UserProfiles.UserNotFoundException userEx)
			{
				Logger.Log(ErrorLevel.Warning,"Failed to get profile class for user: " + domainName+",Error: "+userEx.Message);
				
			}
			return sResults;

		}
		/// <summary>
		/// This method adds the portal listings to the Area specified by the AreaID
		/// </summary>
		/// <param name="portalRoot">This is the URL to the Portal</param>
		/// <param name="AreaID">ID of the area</param>
		/// <param name="listingsContainer">This is the container containig the listings</param>
		/// <param name="folderPath"></param>
		/// <returns></returns>
		public bool AddListings(string portalRoot,Guid AreaID, DataContainer listingsContainer, string folderPath)
		{
		
			try
			{
				if(null == ThisPortalContext)
				{
					Uri siteUri = new Uri(portalRoot);
					TopologyManager topology = new TopologyManager();
					PortalSite portalSite = topology.PortalSites[siteUri];
					ThisPortalContext = PortalApplication.GetContext(portalSite);
				}

				Area area=AreaManager.GetArea(ThisPortalContext,AreaID);
				string xmlFileName="\\items.xml";
				bool returnValue=true;
				if(null==listingsContainer.RelativeitemXML)
					listingsContainer.RelativeitemXML="";
			
				if(listingsContainer.RelativeitemXML.Length>0)
				{
					string xmlPath = folderPath + listingsContainer.RelativeitemXML;
					if(File.Exists(xmlPath))
					{
						List list=new List();
						List listofFailedItems=null;
						// A FileStream is needed to read the XML document.
						FileStream fs = new FileStream(xmlPath, FileMode.Open);
						xmlFileName=fs.Name.Substring(fs.Name.LastIndexOf("\\"),fs.Name.Length-fs.Name.LastIndexOf("\\"));
						XmlReader reader = new XmlTextReader(fs);
						// Declare an object variable of the type to be deserialized.
						// Create an instance of the XmlSerializer specifying type and namespace.
						XmlSerializer serializer = new 	XmlSerializer(typeof(List));
			
						try
						{	
							// Use the Deserialize method to restore the object's state.
							list = (List) serializer.Deserialize(reader);
						}
						catch(InvalidOperationException ex)
						{
							string message=ex.InnerException.Message;
							Logger.Log(ErrorLevel.Error,"Error loading "+xmlPath+": " + ex.Message+"\t"+message);
							return false;
						}
						finally
						{
							reader.Close();
							fs.Close();
						}

						
						if(list.Profiles.Count > 0) //check that there are items in the item XML
						{
							foreach(Profile profile in list.Profiles)
							{

								if(profile.Name==listingsContainer.Template)
								{
									foreach(Item item in profile.Items)
									{
										string title="";
										string description="";
										string url="";
										ListingType type=ListingType.ExternalUrl;

										foreach(Itemfield field in item.Fields)
										{
											switch (field.Name.ToLower())
											{
												case "title":
													title=field.Value;
													break;
												case "description":
													description=field.Value;
													break;
												case "type":
													type=(ListingType)Enum.Parse(typeof(ListingType), field.Value) ;
													break;

												case "url":
													url=field.Value;
													break;

											}
										}
										AreaListing listing=area.Listings.AddListing(title,description,type,url,null);
										

									}
								}
							}


						}
					}
				}

				//					
					
			}
			catch(SPException sPEx)
			{
				Logger.Log(ErrorLevel.Error,"Exception when adding a portal listing. Exception: "+sPEx.Message);
			
			}
			catch(Exception Ex)
			{
				Logger.Log(ErrorLevel.Error,"Exception when adding a portal listing. Exception: "+Ex.Message);
				throw Ex;
			}
			return true;


		}
		/// <summary>
		/// This method adds the portal listings specified in the parameter categories to the portal
		/// </summary>
		/// <param name="portalRoot">This is the URL to the Portal</param>
		/// <param name="categories">This is the DataSet containing the portal listings</param>
		public void AddCategoryListings(string portalRoot,System.Data.DataSet categories)
		{
			try
			{
				if(null == ThisPortalContext)
				{
					Uri siteUri = new Uri(portalRoot);
					TopologyManager topology = new TopologyManager();
					PortalSite portalSite = topology.PortalSites[siteUri];
					ThisPortalContext = PortalApplication.GetContext(portalSite);
				}

				DataTable tbl=categories.Tables["Import"];

				DataRow[] currRows = tbl.Select(null,"Category ASC");
				string sAreaOld="";
				Area area=null;

				foreach(DataRow row in currRows)
				{
					string sArea=row["Category"].ToString();
					while(sArea.Substring(0,1)=="/")
						sArea=sArea.Substring(1,sArea.Length-1);
					string sURL=row["URL"].ToString();

					if(sArea!=sAreaOld)
					{
						Guid gAreaGuid=new Guid(GetSystemAreaGuid(sArea));
						sAreaOld=sArea;
						area=AreaManager.GetArea(ThisPortalContext,gAreaGuid);
					}
					area.Listings.AddListing(row["Title"].ToString(),"",ListingType.ExternalUrl,sURL,null);
					Logger.Log(ErrorLevel.Information,"Added a portal listing "+sURL+" to area "+sArea);
					
				}
			}
			catch(SPException sPEx)
			{
				Logger.Log(ErrorLevel.Error,"Exception when adding a portal listing. Exception: "+sPEx.Message);
			
			}
			catch(Exception Ex)
			{
				Logger.Log(ErrorLevel.Error,"Exception when adding a portal listing. Exception: "+Ex.Message);
				throw Ex;
			}


		}
		/*
		/// <summary>
		/// Helper function for reading data from an XML node
		/// </summary>
		/// <param name="fieldName">This is the name of the field</param>
		/// <param name="xmlItemNode">This is the XML node from which the value is read</param>
		/// <param name="defaultValue">This is the default value of the field</param>
		/// <returns></returns>
		private string GetNodeValue(string fieldName, XmlNode xmlItemNode, string defaultValue)
		{
			string fieldValue = defaultValue;
			try
			{
				fieldValue= xmlItemNode.SelectSingleNode(fieldName).InnerText;
			}
			
			catch (Exception e)
			{
				Logger.Log(ErrorLevel.Information,e.Message);
				
			}
			return fieldValue;
		}

*/
	}
	internal class NativeMethods
	{
		public const int SECURITY_BUILTIN_DOMAIN_RID							= 32;
		public const int DOMAIN_ALIAS_RID_ADMINS							    = 544;
	    
		public enum SID_AUTHORITY
		{
			SECURITY_NULL_SID_AUTHORITY = 0,
			SECURITY_WORLD_SID_AUTHORITY = 1,
			SECURITY_LOCAL_SID_AUTHORITY = 2,
			SECURITY_CREATOR_SID_AUTHORITY = 3,
			SECURITY_NT_AUTHORITY = 5
		};

		public enum RID_AUTHORITY
		{
			SECURITY_WORLD_RID = 0
		};

		[StructLayout(LayoutKind.Sequential)]
			public struct SID_IDENTIFIER_AUTHORITY 
		{ 
			[MarshalAs(UnmanagedType.ByValArray, SizeConst=6)] public byte[] Value; 
		}; 

		[StructLayout(LayoutKind.Sequential)]
			public struct SID 
		{
			public byte  Revision;
			public byte  SubAuthorityCount;
			[MarshalAs(UnmanagedType.Struct)] public SID_IDENTIFIER_AUTHORITY IdentifierAuthority;
			[MarshalAs(UnmanagedType.ByValArray, SizeConst=15)] public int[] SubAuthority;
		};

		public enum SID_NAME_USE 
		{
			SidTypeUser				= 1,
			SidTypeGroup			= 2,
			SidTypeDomain			= 3,
			SidTypeAlias			= 4,
			SidTypeWellKnownGroup	= 5,
			SidTypeDeletedAccount	= 6,
			SidTypeInvalid			= 7,
			SidTypeUnknown			= 8,
			SidTypeComputer			= 9
		};

		[StructLayout(LayoutKind.Sequential)]
			public struct _USER_INFO_10 
		{
			[MarshalAs(UnmanagedType.LPWStr)] public string name;
			[MarshalAs(UnmanagedType.LPWStr)] public string comment;
			[MarshalAs(UnmanagedType.LPWStr)] public string usr_comment;
			[MarshalAs(UnmanagedType.LPWStr)] public string fullname;
		}

		/*		[DllImport("Netapi32.dll", CharSet=CharSet.Unicode, CallingConvention=CallingConvention.Winapi, SetLastError = true)]
				public static extern int NetUserGetInfo(
					string domainController, //Domain controller 
					string username, //Name of user. 
					int level, //Set to 10 to retrieve user information about username user.
					out IntPtr pInfo); 
				public static bool NetUserGetInfo(string domainController, string username, int level, ref _USER_INFO_10 info)
				{
					IntPtr pInfo;
					//If user name is of form domain\name, extract the name from it.
					if (username.IndexOf("\\") > 0) 
					{
						username = username.Substring(username.IndexOf("\\")+1);
					}
					int result = NetUserGetInfo(domainController, username, level, out pInfo);
					if(0 == result) //Success
					{
						info = (_USER_INFO_10) Marshal.PtrToStructure(pInfo, typeof(_USER_INFO_10));
						return true;
					}
					else
					{
						return false;
					}
				}

				[DllImport("Netapi32.dll", CharSet=CharSet.Unicode, CallingConvention=CallingConvention.Winapi, SetLastError = true)]
					//Returns the name of the primary domain controller (PDC). 
				public static extern int NetGetDCName(
					string servername, 	//DNS or NetBIOS name of the remote server on which the function is to execute
					string domainname,	//Name of the domain. If this parameter is NULL, the function returns the name of the domain controller for the primary domain.
					out string domainController);


				[DllImport("advapi32.dll", CharSet=CharSet.Unicode, CallingConvention=CallingConvention.Winapi, SetLastError = true)]
				public static extern bool ConvertSidToStringSid(
					ref SID Sid,				// security identifier
					out IntPtr StringSid			// receive pointer to string buffer
					);

				[DllImport("kernel32.dll", CharSet=CharSet.Unicode, CallingConvention=CallingConvention.Winapi, SetLastError = true)]
				public static extern int GetLastError();

				[DllImport("advapi32.dll", CharSet=CharSet.Unicode, CallingConvention=CallingConvention.Winapi, SetLastError = true)]
				public static extern bool LookupAccountSid(
					string SystemName,		// name of local or remote computer
					ref SID Sid,				// security identifier
					StringBuilder Name,			// account name buffer
					ref System.Int32  cbName,			// size of account name buffer
					StringBuilder DomainName,		// domain name
					ref System.Int32  cbDomainName,	// size of domain name buffer
					ref SID_NAME_USE peUse		// SID type
					);
	
		*/
		[DllImport("advapi32.dll", CharSet=CharSet.Unicode, CallingConvention=CallingConvention.Winapi, SetLastError = true)]
		private static extern bool LookupAccountName(
			string		strlpSystemName,    	// system name
			string		strAccountName,		// account name
			out SID 	Sid,			// security identifier
			ref System.Int32	cbSid,				// size of security identifier
			StringBuilder		DomainName,			// domain name
			ref System.Int32	cbDomainName,		// size of domain name
			out SID_NAME_USE	peUse				// SID-type indicator
			);

		// Added this function to Advapi class to get the SID of a user as a byte array - kshamtaj [07/23/2003]
		public static byte[] LookupAccountName(string	strAccountName)
		{
			Int32 cbSidSize = 0;
			Int32 cbDomainNameSize = 0;
			NativeMethods.SID_NAME_USE peUse;
			NativeMethods.SID sid = new NativeMethods.SID();
			StringBuilder DomainName = null;

			//The first call gets the cbDomainNameSize
			LookupAccountName( null, strAccountName, out sid, ref cbSidSize, DomainName, ref cbDomainNameSize, out peUse );
			DomainName = new StringBuilder( cbDomainNameSize );

			//The second call gets the sid
			LookupAccountName(null, strAccountName, out sid, ref cbSidSize, DomainName, ref cbDomainNameSize, out peUse);

			if(NativeMethods.IsValidSid(ref sid))
			{
				//copy the SID to a byte array
				int intSIDSize = NativeMethods.GetLengthSid(ref sid);
				byte[] bSid = new byte[intSIDSize];
				//we check the sid size to 8 as that is the minimum size we assume every SID is going to be
				if(bSid != null && intSIDSize > 8)
				{
					int intIndex = 0;
					int i;
					bSid[intIndex++] = sid.Revision;
					bSid[intIndex++] = sid.SubAuthorityCount;
					for (i = 0; i < 6 && intIndex < intSIDSize; i++)
					{
						bSid[intIndex++] = sid.IdentifierAuthority.Value[i];
					}
					if(i < 6)
					{
						//not enough space in the byte array
						return null;
					}
					for (i = 0; i < sid.SubAuthorityCount && intIndex < intSIDSize; i++)
					{
						byte [] bTemp = BitConverter.GetBytes(sid.SubAuthority[i]);
						for (int j = 0; j < bTemp.Length; j++)
						{
							bSid[intIndex++] = bTemp[j];
						}
					}
					if(i < sid.SubAuthorityCount)
					{
						//not enough space in the byte array
						return null;
					}
				}
				return bSid ;
			}
			//Sid was not valid
			return null; 
		}

		[DllImport("advapi32.dll", CharSet=CharSet.Unicode, CallingConvention=CallingConvention.Winapi, SetLastError = true)]
		public static extern int GetLengthSid(
			ref SID		Sid			//security identifier
			);

		[DllImport("advapi32.dll", CharSet=CharSet.Unicode, CallingConvention=CallingConvention.Winapi, SetLastError = true)]
		public static extern bool InitializeSid(
			ref SID Sid,											// SID
			ref SID_IDENTIFIER_AUTHORITY pIdentifierAuthority,	// SIA
			byte nSubAuthorityCount							// count of subauthorities
			);
			
		[DllImport("advapi32.dll", CharSet=CharSet.Unicode, CallingConvention=CallingConvention.Winapi, SetLastError = true)]
		public static extern bool IsValidSid(
			ref SID		Sid			//security Identifier
			);

		[DllImport("advapi32.dll", CharSet=CharSet.Unicode, CallingConvention=CallingConvention.Winapi, SetLastError = true)]
		public static extern bool CheckTokenMembership(
			IntPtr hToken,
			ref SID Sid,
			ref bool pfIsMember);

		public static bool IsCurrentUserMemberOfLocalAdmin()
		{
			SID                         AdminSID    =   new SID();            
			SID_IDENTIFIER_AUTHORITY    sid         =   new SID_IDENTIFIER_AUTHORITY();
			bool                        fIsMember   =   false;
            
			//create the well known sid for local admin
			sid.Value = new byte[6] {0, 0, 0, 0, 0, (byte)SID_AUTHORITY.SECURITY_NT_AUTHORITY};
            
			AdminSID.SubAuthority = new int[15] {SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
			AdminSID.IdentifierAuthority  = sid;
				
			if(!InitializeSid(ref AdminSID, ref sid, 2))
			{
				//Win32Exception() constructor will call GetLastWin32Error()
				throw new Win32Exception();
			}
			else
			{
				IntPtr intptrNULL  = new IntPtr(0);
                
				if(IsValidSid(ref AdminSID))
				{
					if(!CheckTokenMembership(
						intptrNULL,
						ref AdminSID,
						ref fIsMember))
					{
						//Win32Exception() constructor will call GetLastWin32Error()
						throw new Win32Exception();
					}
					else
					{
						return fIsMember;
					}
				}
				else
				{
					//Win32Exception() constructor will call GetLastWin32Error()
					throw new Win32Exception();
				}
			}
		}
	}
	
}
